﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Auction_Intranet.Models;
using AuctionDataLayer;
using Auction_Intranet.Helpers;
using System.Configuration;
using System.Transactions;

namespace Auction_Intranet.Controllers
{
    [HandleError]
    public class AdminController : ParentController
    {
        DataRepository m_rep = new DataRepository();
        List<string> admins = (ConfigurationManager.AppSettings["AdminUsers"]).Split(',').ToList();

        public ActionResult ErrorLog()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            var model = m_rep.getErrorLog();
            return View(model);
        }

        //[Authorize(Users = @"patrekur-THINK\patrekur")]
        public ActionResult DailyCalculationsGurobi()
        { 
            string username = (User.Identity.Name).Split('\\')[1];
            if (admins.Contains(username))
            {
                if (username == "patrekur" || username == "gudrun")
                {
                    using (var transaction = new TransactionScope())
                    {
                        GurobiCalculations cal = new GurobiCalculations();
                        cal.DayliCalculations();
                        transaction.Complete();                        
                        return View();
                    }                      
                }
                return RedirectToAction("Index");
            }
            return RedirectToAction("Index", "Dashboard");
        }

        public ActionResult Index()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            //int tempid = 873;
            //var allGroupMembers1 = m_rep.GetMembersOfGroupById(tempid);
            //var allGroupMembers2 = m_rep.GetMembersOfGroupByIdAll(tempid);
            //foreach (var item in allGroupMembers1)
            //{
            //    System.Diagnostics.Trace.WriteLine("username: " + item.User.Username + ". Email: " + item.User.Email);
            //}
            //foreach (var item in allGroupMembers2)
            //{
            //    System.Diagnostics.Trace.WriteLine("username: " + item.User.Username + ". Email: " + item.User.Email);
            //}
            return View();
        }

        public ActionResult AddRUUser()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            AddRUUserModel model = new AddRUUserModel();
            return View(model);
        }

        [HttpPost, ActionName("AddRUUser")]
        public ActionResult AddRUUserConfirm(AddRUUserModel model)
        {
            if (ModelState.IsValid)
            {
                var memberToAdd = m_rep.getRUUserByUserName(model.username);
                var exists = m_rep.GetUserByUsername(model.username);
                if (memberToAdd != null && exists == null)
                {
                    User newUser = m_rep.getOrCreateRUUserByUserName(memberToAdd.sUser);
                    //newUser.Username = username;
                    //newUser.Balance = 500;
                    m_rep.AddNewUserForAuction(newUser);

                    //Create a group for this user only  
                    Group group = new Group();
                    group.Created = DateTime.Now;
                    group.Name = memberToAdd.sUser;
                    group.Balance = newUser.Balance;
                    m_rep.CreateNewSingleGroup(group);

                    //Add him to his group 
                    UserInGroup userInGroup = new UserInGroup();
                    userInGroup.UserId = newUser.Id;
                    userInGroup.GroupId = group.Id;
                    userInGroup.CreditAdded = newUser.Balance;
                    userInGroup.ActiveMember = true;
                    m_rep.AddMemberToSingleGroup(userInGroup);

                    m_rep.UpdadeUserSingleGroupId(newUser.Id, group.Id);
                    return RedirectToAction("Users");
                }
                else
                {
                    ModelState.AddModelError("username", "Username does not exist or has already been added");
                    return View(model);
                }
            }
            return View(model);
        }

        //Helper for adding ru user to auction
        //TODO : Parse string before sending to db. sql injections
        public ActionResult CollectUsernames(string query)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return Json("", JsonRequestBehavior.AllowGet);
            }
            var users = m_rep.GetAllRUUsernamesForQuery(query);
            if (users != null)
            {
                IEnumerable<string> auctionUsers = m_rep.GetAllUsers().Select(x => x.Username);
                var newlist = users.Where(x => !auctionUsers.Contains(x.sUser));

                List<object> results = new List<object>();
                foreach (var item in newlist)
                {
                    var temp = new { username = item.sUser, name = item.sName };
                    results.Add(temp);
                }
                return Json(results, JsonRequestBehavior.AllowGet);
            }            
            return Json("", JsonRequestBehavior.AllowGet);
        }

        public ActionResult Users()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            var model = m_rep.GetAllUsers().OrderBy(x => x.Username);
            return View(model);
        }

        public ActionResult EditUserBalance(int? id)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            if (id.HasValue)
            {
                int realId = id.Value;
                var result = m_rep.GetUserById(realId);
                UpdateUserBalanceModel model = new UpdateUserBalanceModel();
                model.id = result.Id;
                model.username = result.Username;
                model.balance = result.Balance;
                if (model != null)
                {
                    return View(model);
                }
            }
            return View("NotFound");
        }

        [HttpPost, ActionName("EditUserBalance")]
        public ActionResult EditUserBalanceConfirm(UpdateUserBalanceModel model)
        {
            if (ModelState.IsValid)
            {
                var result = m_rep.GetUserById(model.id);
                if (result != null)
                {
                    //Update user balance
                    m_rep.UpdateUserBalance(model.balance, model.id);
                    //Update his single group balance
                    m_rep.UpdateGroupBalance(model.balance, result.MyGroupId);
                    //Update his user in group transaction
                    m_rep.UpdateUserInGroupCreditAdded(model.balance, result.Id, result.MyGroupId);
                    return RedirectToAction("Users");
                }
                return View("Error");
            }
            return View(model);
        }

        public ActionResult Rooms()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            IEnumerable<Room> rooms = m_rep.GetAllRooms();
            List<RoomModel> model = new List<RoomModel>();
            foreach (var item in rooms)
            {
                RoomModel room = new RoomModel();
                room.room = item;
                //room.amenities = m_rep.GetAmenitiesByRoomBy(item.Id);
                room.pictures = m_rep.GetRoomPicturesByRoomId(item.Id);
                if (room.pictures.Count() >= 4)
                {
                    room.allowAddPicture = "hide";
                }
                model.Add(room);
            }
            

            if (model != null)
            {
                return View(model);
            }
            return View(model);
        }

        public ActionResult DeletePicture(int picId, int roomId)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return Json("", JsonRequestBehavior.AllowGet); 
            }
            var pic = m_rep.GetRoomPIctureById(picId, roomId);
            if (pic != null)
            {
                var pictureIDd = pic.Id;
                //Delete picture from database
                m_rep.DeleteRoomPicture(pic);
                                
                //Delete picture from folders(Thumb and full version)
                String serverPath = Server.MapPath("~");
                String imagesPath = serverPath + "\\Content\\Photos\\Rooms\\";
                String thumbPath = imagesPath + "Thumb\\";
                String fullPath = imagesPath + "Full\\";

                String FullFilePath = thumbPath + pictureIDd + ".jpg";
                String ThumbFilePath = fullPath + pictureIDd + ".jpg";

                FileHelper.DeleteFile(FullFilePath);
                FileHelper.DeleteFile(ThumbFilePath);

                return Json(1, JsonRequestBehavior.AllowGet);
            }
            return Json("", JsonRequestBehavior.AllowGet);             
        }

        public ActionResult AddPicture(int? id)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            if (id.HasValue)
            {                
                int realId = id.Value;
                int roomPicturesCount = m_rep.GetRoomPicturesByRoomId(realId).Count();
                if (roomPicturesCount >= 4)
                {
                    return RedirectToAction("Rooms");
                }
                PictureModelAdd model = new PictureModelAdd();
                model.roomId = realId;
                return View(model);
            }
            return RedirectToAction("Rooms");
        }

        [HttpPost, ActionName("AddPicture")]
        public ActionResult AddPictureConfirm(PictureModelAdd model)
        {
            if (ModelState.IsValid)
            {
                String serverPath = Server.MapPath("~");
                String imagesPath = serverPath + "\\Content\\Photos\\Rooms\\";
                String thumbPath = imagesPath + "Thumb\\";
                String fullPath = imagesPath + "Full\\";

                //Add picture 
                RoomPicture pic = new RoomPicture();
                pic.RoomId = model.roomId;
                m_rep.AddNewRoomPicture(pic);
                String fileName = pic.Id.ToString();
                FileHelper.ResizeAndSave(thumbPath, fileName, model.ImageUploaded.InputStream, 80, true);
                FileHelper.ResizeAndSave(fullPath, fileName, model.ImageUploaded.InputStream, 700, false);

                return RedirectToAction("Rooms");
            }
            return View(model);
        }

        //
        // GET: /Admin/Details/5
        public ActionResult DetailsRoom(int? id)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            if (id.HasValue)
            {
                int realId = id.Value;
                var room = m_rep.getRoomById(realId);
                var amenities = m_rep.GetAmenitiesByRoomBy(room.Id);
                var pictures = m_rep.GetRoomPicturesByRoomId(room.Id);
                RoomModel model = new RoomModel();
                model.room = room;
                model.amenities = amenities;
                model.pictures = pictures;
                return View(model);
            }
            return View("NotFound");
        }

        //
        // GET: /Admin/Create
        public ActionResult CreateRoom()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            CreateRoomModel model = new CreateRoomModel();
            return View(model);
        } 

        //
        // POST: /Admin/Create
        [HttpPost, ActionName("CreateRoom")]
        public ActionResult CreateRoomConfirm(CreateRoomModel model)
        {
            if (ModelState.IsValid)
            {
                Room room = new Room();
                room.Name = model.name;
                room.Location = model.location;
                room.Capacity = model.capacity;
                room.Size = model.size;
                room.Deleted = false;

                //Add room to database
                m_rep.addNewRoom(room);

                List<RoomAmenity> roomAmenities = new List<RoomAmenity>();
                foreach (var item in model.myAmenities)
                { 
                    //Add amenity to room
                    RoomAmenity amenity = new RoomAmenity();
                    amenity.RoomId = room.Id;
                    amenity.AmenityId = Convert.ToInt32(item);
                    roomAmenities.Add(amenity);
                }
                //Add all amenities to room
                m_rep.AddRoomAmenities(roomAmenities);

                String serverPath = Server.MapPath("~");
                String imagesPath = serverPath + "\\Content\\Photos\\Rooms\\";
                String thumbPath = imagesPath + "Thumb\\";
                String fullPath = imagesPath + "Full\\";

                //Add picture 1
                RoomPicture pic1 = new RoomPicture();
                pic1.RoomId = room.Id;
                m_rep.AddNewRoomPicture(pic1);
                String fileName = pic1.Id.ToString();
                FileHelper.ResizeAndSave(thumbPath, fileName, model.ImageUploaded1.InputStream, 80, true);
                FileHelper.ResizeAndSave(fullPath, fileName, model.ImageUploaded1.InputStream, 700, false);

                //Add picture 2
                RoomPicture pic2 = new RoomPicture();
                pic2.RoomId = room.Id;
                m_rep.AddNewRoomPicture(pic2);
                fileName = pic2.Id.ToString();
                FileHelper.ResizeAndSave(thumbPath, fileName, model.ImageUploaded2.InputStream, 80, true);
                FileHelper.ResizeAndSave(fullPath, fileName, model.ImageUploaded2.InputStream, 700, false);

                //Add picture 3
                RoomPicture pic3 = new RoomPicture();
                pic3.RoomId = room.Id;
                m_rep.AddNewRoomPicture(pic3);
                fileName = pic3.Id.ToString();
                FileHelper.ResizeAndSave(thumbPath, fileName, model.ImageUploaded3.InputStream, 80, true);
                FileHelper.ResizeAndSave(fullPath, fileName, model.ImageUploaded3.InputStream, 700, false);

                //Add picture 4
                RoomPicture pic4 = new RoomPicture();
                pic4.RoomId = room.Id;
                m_rep.AddNewRoomPicture(pic4);
                fileName = pic4.Id.ToString();
                FileHelper.ResizeAndSave(thumbPath, fileName, model.ImageUploaded4.InputStream, 80, true);
                FileHelper.ResizeAndSave(fullPath, fileName, model.ImageUploaded4.InputStream, 700, false);

                return RedirectToAction("Rooms");
            }
            return View(model);
        }
        
        //
        // GET: /Admin/Edit/5
        public ActionResult EditRoom(int id)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            EditRoomModel model = new EditRoomModel();
            var room = m_rep.getRoomById(id);
            model.name = room.Name;
            model.location = room.Location;
            model.capacity = room.Capacity;
            model.size = room.Size;
            
            var tempAmenities = m_rep.GetAllAmenities();
            var selectedAmenities = m_rep.GetAmenitiesByRoomBy(room.Id);
            List<AmenityModel> realAmenities = new List<AmenityModel>();
            
            foreach (var item in tempAmenities)
            {
                AmenityModel temp = new AmenityModel();
                temp.id = item.Id;
                temp.name = item.Name;
                temp.selected = false;
                bool isSelected = selectedAmenities.Select(x => x.AmenityId).Contains(item.Id);
                if (isSelected)
                {
                    temp.selected = true;
                }                
                realAmenities.Add(temp);
            }
           
            model.amenities = realAmenities;
            return View(model);
        }

        //
        // POST: /Admin/Edit/5
        [HttpPost, ActionName("EditRoom")]
        public ActionResult EditRoomConfirm(EditRoomModel model)
        {
            if (ModelState.IsValid)
            {
                Room room = new Room();
                room.Id = model.id;
                room.Name = model.name;
                room.Location = model.location;
                room.Capacity = model.capacity;
                room.Size = model.size;
                room.Deleted = false;

                //Add room to database
                m_rep.updateRoom(room);

                //remove current room amenites
                IEnumerable<RoomAmenity> currentRoomAmenities = m_rep.GetAmenitiesByRoomBy(model.id);
                m_rep.DeleteRoomsAmenities(currentRoomAmenities);

                if (model.myAmenities != null)
                {
                    List<RoomAmenity> roomAmenities = new List<RoomAmenity>();
                    foreach (var item in model.myAmenities)
                    {
                        //Add amenity to room
                        RoomAmenity amenity = new RoomAmenity();
                        amenity.RoomId = model.id;
                        amenity.AmenityId = Convert.ToInt32(item);
                        roomAmenities.Add(amenity);
                    }
                    //Add updated amenities to room: new amenities list
                    m_rep.AddRoomAmenities(roomAmenities);
                }

                return RedirectToAction("Rooms");
            }
            var tempAmenities = m_rep.GetAllAmenities();
            var selectedAmenities = m_rep.GetAmenitiesByRoomBy(model.id);
            List<AmenityModel> realAmenities = new List<AmenityModel>();

            foreach (var item in tempAmenities)
            {
                AmenityModel temp = new AmenityModel();
                temp.id = item.Id;
                temp.name = item.Name;
                temp.selected = false;
                bool isSelected = selectedAmenities.Select(x => x.AmenityId).Contains(item.Id);
                if (isSelected)
                {
                    temp.selected = true;
                }
                realAmenities.Add(temp);
            }

            model.amenities = realAmenities;
            return View(model);
        }

        //
        // GET: /Admin/Delete/5
        public ActionResult DeleteRoom(int? id)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            if(id.HasValue)
            {                 
                int realId = id.Value;
                var room = m_rep.getRoomById(realId);                
                var amenities = m_rep.GetAmenitiesByRoomBy(room.Id);
                var pictures = m_rep.GetRoomPicturesByRoomId(room.Id);
                RoomModel model = new RoomModel();
                model.room = room;
                model.amenities = amenities;
                model.pictures = pictures;
                return View(model);
            }
            return View("NotFound");
        }

        //
        // POST: /Admin/Delete/5
        [HttpPost, ActionName("DeleteRoom")]
        public ActionResult DeleteRoomConfirm(int? id)
        {
            if (id.HasValue)
            {
                int realId = id.Value;
                Room room = m_rep.getRoomById(realId);
                room.Deleted = true;
                //Soft Delete room
                m_rep.updateRoom(room);                
            }
            return RedirectToAction("Rooms");
        }

        [HttpPost]
        public ActionResult GetBidResultsByDate(AdminSingleViewResultModel model)
        {
            var dateTicks = DateTime.Now.Ticks;
            if(ModelState.IsValid)
            {
                dateTicks = model.postData.bidDate.Ticks;
                var roomId = model.postData.RoomId;
                return RedirectToAction("Statistics", new { id = roomId, ticks = dateTicks });
            }            
            return RedirectToAction("Statistics", new { id = model.postData.RoomId, ticks = dateTicks , valid = 0});
        }

        //
        // GET: /Admin/Statistics
        public ActionResult Statistics(int? id, long? ticks, int? valid)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            if (valid.HasValue)
            {
                int realvalid = valid.Value;
                if (realvalid == 0)
                {
                    ModelState.AddModelError("", " :-( Invalid date format");
                }
            }
            List<Room> rooms = m_rep.GetAllRooms().ToList();
            AdminSingleViewResultModel model = new AdminSingleViewResultModel();
            model.Rooms = rooms;

            List<AvailableBidTime> times = m_rep.GetAvailableBidTimes().ToList();
            model.bidTimes = times;

            int realId = 0;
            if (id.HasValue)
            {
                realId = id.Value;
            }
            else
            {
                realId = rooms.First().Id;
            }
            DateTime date = DateTime.Now;
            if (ticks.HasValue)
            {
                long ticksDate = ticks.Value;
                date = new DateTime(ticksDate);
            }

            Room room = m_rep.getRoomById(realId);
            model.postData = new GeBidResultModelAdmin();
            model.postData.bidDate = date;
                        
            if (room != null)
            {
                IEnumerable<Bid> bids = m_rep.GetAllBidsByDate(date).Where(x => x.StateId == 2 && x.RoomId == room.Id);
                model.room = room;
                model.DayResults = bids;
                model.currentDateResult = date;
                model.postData.RoomId = room.Id;
                return View(model);
            }
            return View("NotFound");
        }

        public ActionResult _Statistics_RoomMenu()
        {
            List<Room> model = m_rep.GetAllRooms().ToList();
            return View(model);
        }

        [HttpPost]
        public ActionResult GetBidResultsByDateAllRooms(BidResultAdminModel model)
        {
            var dateTicks = DateTime.Now.Ticks;
            if (ModelState.IsValid)
            {
                dateTicks = model.postData.bidDate.Ticks;
                return RedirectToAction("AllRoomsView", new { ticks = dateTicks });
            }
            return RedirectToAction("AllRoomsView", new { ticks = dateTicks, valid = 0 });
        }

        public ActionResult AllRoomsView(long? ticks, int? valid)
        {
            if (valid.HasValue)
            {
                int realvalid = valid.Value;
                if (realvalid == 0)
                {
                    ModelState.AddModelError("", "Invalid date format");
                }
            }
            DateTime date = DateTime.Now;
            if (ticks.HasValue)
            {
                long ticksDate = ticks.Value;
                date = new DateTime(ticksDate);
            }           

            BidResultAdminModel model = new BidResultAdminModel();

            model.postData = new GeBidResultModelAdmin();
            model.postData.bidDate = date;

            model.Rooms = m_rep.GetAllRooms();
            model.Times = m_rep.GetAvailableBidTimes().ToList();
            model.CurrentDateResult = date;
            model.Bids = m_rep.GetAllBidsByDate(model.CurrentDateResult).Where(x => x.StateId == 2);

            return View(model);
        }

        public ActionResult Amenities()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            var result = m_rep.GetAllAmenities();
            return View(result);
        }

        public ActionResult CreateAmenitie()
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            var model = new AmenityModelCreate();
            return View(model);
        }

        [HttpPost, ActionName("CreateAmenitie")]
        public ActionResult CreateAmenitieConfirm(Amenity model)
        {
            if (ModelState.IsValid)
            {
                Amenity result = new Amenity();
                result.Name = model.Name;
                result.Active = true;
                m_rep.addAmenity(result);
                return RedirectToAction("Amenities");
            }
            return View(model);
        }

        public ActionResult DeleteAmenity(int? id)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            if (id.HasValue)
            {
                int realId = id.Value;
                var model = m_rep.GetAmenitieById(realId);
                if (model != null)
                {
                    return View(model);
                }
            }
            return View("NotFound");
        }

        [HttpPost, ActionName("DeleteAmenity")]
        public ActionResult DeleteAmenityConfirm(int? id)
        {
            if (id.HasValue)
            {
                int realId = id.Value;
                var model = m_rep.GetAmenitieById(realId);
                if (model != null)
                {
                    m_rep.DeleteAmenitie(model);
                }
            }
            return RedirectToAction("Amenities");
        }

        public ActionResult EditAmenity(int? id)
        {
            string username = (User.Identity.Name).Split('\\')[1];
            if (!admins.Contains(username))
            {
                return RedirectToAction("Index", "Dashboard");
            }
            if (id.HasValue)
            {
                int realId = id.Value;
                var result = m_rep.GetAmenitieById(realId);
                AmenityModelCreate model = new AmenityModelCreate();
                model.id = result.Id;
                model.name = result.Name;                
                if (model != null)
                {
                    return View(model);
                }                
            }
            return View("NotFound");
        }

        [HttpPost, ActionName("EditAmenity")]
        public ActionResult EditAmenityConfirm(AmenityModelCreate model)
        {
            if (ModelState.IsValid)
            {
                var result = m_rep.GetAmenitieById(model.id);
                if (result != null)
                {
                    m_rep.updateAmenity(result, model.name);
                    return RedirectToAction("Amenities");
                }
                return View("Error");
            }
            return View(model);
        }
    }
}

